#!/bin/bash
# 修复DNS缓存污染(解析错误)的智能运维脚本
FIX_CODE_ID="dns-cache-pollution"

# 定义相关配置文件路径
RESOLV_CONF="/etc/resolv.conf"
SYSTEMD_RESOLVED_CONF="/etc/systemd/resolved.conf"
DNSMASQ_CONF="/etc/dnsmasq.conf"

# 备份文件函数
backup_file() {
    local file="$1"
    if [ -f "$file" ]; then
        local backup="${file}.bak.$(date +%Y%m%d%H%M%S)"
        cp -a "$file" "$backup"
        echo "已备份配置文件: $backup"
    fi
}

# 检测当前DNS配置
check_dns_config() {
    echo "==== 当前DNS配置检测 ===="
    
    # 显示当前DNS服务器
    echo "当前DNS服务器配置:"
    if [ -f "$RESOLV_CONF" ]; then
        cat "$RESOLV_CONF" | grep -v '^#' | grep -v '^$'
    else
        echo "$RESOLV_CONF 不存在"
    fi
    
    # 检查是否使用systemd-resolved
    if command -v systemctl &> /dev/null && systemctl is-active --quiet systemd-resolved; then
        echo -e "\nsystemd-resolved 状态: 运行中"
        resolvectl status | grep "DNS Servers"
    fi
    
    # 检查是否使用dnsmasq
    if command -v systemctl &> /dev/null && systemctl is-active --quiet dnsmasq; then
        echo -e "\ndnsmasq 状态: 运行中"
        if [ -f "$DNSMASQ_CONF" ]; then
            grep '^server=' "$DNSMASQ_CONF" | grep -v '^#'
        fi
    fi
    
    echo -e "\nDNS解析测试 (google.com):"
    nslookup google.com 2>/dev/null | grep "Address" | grep -v '#'
    echo "=========================="
    echo
}

# 清除各种DNS缓存
clear_dns_cache() {
    echo "开始清除DNS缓存..."
    
    # 清除systemd-resolved缓存
    if command -v systemctl &> /dev/null && systemctl is-active --quiet systemd-resolved; then
        echo "清除 systemd-resolved 缓存..."
        resolvectl flush-caches
        systemctl restart systemd-resolved
    fi
    
    # 清除dnsmasq缓存
    if command -v systemctl &> /dev/null && systemctl is-active --quiet dnsmasq; then
        echo "清除 dnsmasq 缓存..."
        systemctl restart dnsmasq
    fi
    
    # 清除nscd缓存
    if command -v systemctl &> /dev/null && systemctl is-active --quiet nscd; then
        echo "清除 nscd 缓存..."
        systemctl restart nscd
    else
        if command -v nscd &> /dev/null; then
            nscd -i hosts
        fi
    fi
    
    # 对于使用dnsmasq的NetworkManager配置
    if command -v systemctl &> /dev/null && systemctl is-active --quiet NetworkManager; then
        echo "重启 NetworkManager 以清除DNS缓存..."
        systemctl restart NetworkManager
    fi
    
    echo "DNS缓存清除完成"
    echo
}

# 重置DNS服务器配置为公共DNS
reset_to_public_dns() {
    echo "重置DNS服务器为公共DNS..."
    
    # 备份当前配置
    backup_file "$RESOLV_CONF"
    
    # 对于使用systemd-resolved的系统
    if command -v systemctl &> /dev/null && systemctl is-active --quiet systemd-resolved; then
        backup_file "$SYSTEMD_RESOLVED_CONF"
        
        # 修改resolved配置
        sed -i 's/^#*DNS=.*/DNS=1.1.1.1 8.8.8.8 1.0.0.1 8.8.4.4/' "$SYSTEMD_RESOLVED_CONF"
        sed -i 's/^#*DNSStubListener=.*/DNSStubListener=yes/' "$SYSTEMD_RESOLVED_CONF"
        systemctl restart systemd-resolved
        
        # 重新创建resolv.conf链接
        if [ -L "$RESOLV_CONF" ]; then
            rm -f "$RESOLV_CONF"
        fi
        ln -s /run/systemd/resolve/stub-resolv.conf "$RESOLV_CONF"
    else
        # 直接修改resolv.conf
        echo "# 由 $(basename $0) 脚本重置的DNS配置" > "$RESOLV_CONF"
        echo "nameserver 1.1.1.1  # Cloudflare DNS" >> "$RESOLV_CONF"
        echo "nameserver 8.8.8.8  # Google DNS" >> "$RESOLV_CONF"
        echo "nameserver 1.0.0.1  # Cloudflare DNS 备用" >> "$RESOLV_CONF"
        echo "nameserver 8.8.4.4  # Google DNS 备用" >> "$RESOLV_CONF"
        echo "options timeout:2 attempts:3 rotate" >> "$RESOLV_CONF"
    fi
    
    # 对于dnsmasq配置
    if [ -f "$DNSMASQ_CONF" ]; then
        backup_file "$DNSMASQ_CONF"
        sed -i '/^server=\/.*\//d' "$DNSMASQ_CONF"  # 移除特定域的服务器配置
        sed -i 's/^server=.*/#&/' "$DNSMASQ_CONF"   # 注释现有服务器配置
        echo "server=1.1.1.1" >> "$DNSMASQ_CONF"
        echo "server=8.8.8.8" >> "$DNSMASQ_CONF"
        if command -v systemctl &> /dev/null && systemctl is-active --quiet dnsmasq; then
            systemctl restart dnsmasq
        fi
    fi
    
    echo "已设置公共DNS服务器"
    echo
}

# 检测并修复hosts文件污染
check_hosts_file() {
    echo "检查并修复hosts文件..."
    local hosts_file="/etc/hosts"
    backup_file "$hosts_file"
    
    # 移除异常条目（包含可疑IP段的条目）
    echo "清理可能的恶意hosts条目..."
    sed -i '/^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}[[:space:]]\+[a-zA-Z0-9\.-]\+/ {
        /127.0.0.1/! {
            /::1/! d
        }
    }' "$hosts_file"
    
    # 确保localhost条目存在
    if ! grep -q "^127.0.0.1[[:space:]]\+localhost" "$hosts_file"; then
        echo "127.0.0.1 localhost" >> "$hosts_file"
    fi
    if ! grep -q "^::1[[:space:]]\+localhost" "$hosts_file"; then
        echo "::1 localhost" >> "$hosts_file"
    fi
    
    echo "hosts文件检查和修复完成"
    echo
}

# 测试DNS解析功能
test_dns_resolution() {
    echo "测试DNS解析功能..."
    local test_domains=("google.com" "github.com" "cloudflare.com" "baidu.com")
    local success=0
    local failed=0
    
    for domain in "${test_domains[@]}"; do
        echo -n "测试 $domain: "
        if nslookup "$domain" >/dev/null 2>&1; then
            echo "成功"
            ((success++))
        else
            echo "失败"
            ((failed++))
        fi
    done
    
    echo -e "\n解析测试结果: 成功 $success 个, 失败 $failed 个"
    if [ $failed -gt 0 ]; then
        echo "警告: 仍有 $failed 个域名解析失败，可能需要进一步排查"
    fi
    echo
}

# 主逻辑
echo "开始处理DNS缓存污染(解析错误)问题..."
echo

# 检查当前DNS状态
check_dns_config

# 清除现有DNS缓存
clear_dns_cache

# 检查并修复hosts文件
check_hosts_file

# 重置为公共DNS服务器
reset_to_public_dns

# 测试DNS解析
test_dns_resolution

echo "==== DNS修复操作完成 ===="
echo "操作总结:"
echo "1. 已清除系统DNS缓存"
echo "2. 已检查并清理hosts文件"
echo "3. 已将DNS服务器重置为公共DNS（Cloudflare和Google）"
echo "4. 已进行DNS解析测试"
echo
echo "建议后续操作:"
echo "1. 监控DNS解析情况，确认问题是否解决"
echo "2. 如问题持续，可尝试使用VPN或企业内部DNS"
echo "3. 检查网络环境是否存在持续的DNS污染来源"

exit 0
